跳到主要内容

TCP 的流量控制

为什么需要流量控制?

一条 TCP 连接的双方主机都为该连接设置了接收缓存。当该 TCP 连接接收到按序的字节后,它就将数据放入接收缓存。相关联的应用程序会从该缓存中读取数据,但应用程序不一定能马上将数据取走。接收方应用也许正忙于其他任务,需要过很长时间后才能去读取该数据。如果应用程序读取数据比较慢,而发送方发送数据很快、很多,则很容易使该连接的接收缓存溢出。

流量控制的原理

TCP 为应用程序提供了流量控制(flow control)服务,以解决因发送方发送数据太快而导致接收方来不及接收,使接收方缓存溢出的问题。流量控制的基本方法就是接收方根据自己的接收能力控制发送方的发送速率。

因此,可以说 流量控制是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读速率相匹配。利用滑动窗口机制可以很方便地控制发送方的平均发送速率。TCP 采用接收方控制发送方发送窗口大小的方法来实现在TCP连接上的流量控制。 在 TCP 报文段首部的窗口字段写入的数值就是当前给对方设置的发送窗口数值的上限。这种由接收方控制发送方的做法,在计算机网络中经常使用。发送窗口在连接建立时由双方商定。但在通信的过程中,接收方根据接收缓存中可用缓存的大小,随时动态地调整对方的发送窗口上限值(可增大或减小)。

为此,TCP 接收方要维持一个接收窗口的变量,其值不能大于可用接收缓存大小。

image.png

前面的 图 5-10 已画出了接收缓存与接收窗口的关系。

在 TCP 报文段首部的窗口字段写入的数值就是当前接收方的接收窗口大小。TCP 发送方的发送窗口的大小必须小于该值。后面我们将会看到发送窗口的大小还要受拥塞窗口的限制,在这里我们只考虑流量控制对发送窗口的影响。

如何完成流量控制?

下面通过图 5-15 的例子说明利用可变窗口大小进行流量控制。只考虑 A 向 B 发送数据。假设在连接建立时,

注:这里 rwnd 表示 receiver window,不过这个报文段在图中已经省略了。再假设每一个数据报文段所携带的数据都是 100 字节长,数据报文段序号的初始值为 1(见图中第一个箭头上的 seq=1。图中右边的注释可帮助理解整个的过程)。

请注意:图中大写的 ACK 表示首部中的 ACK 位,小写的 ack 表示确认号字段的值。B 向 A 发送的三个报文段标注了 ACK=1,只有在 ACK 置为 1 时确认号字段才有意义。

image.png

主机 B 进行了三次流量控制。第一次把窗口减小为 300 字节,第二次又把窗口减为 100 字节,最后把窗口减至 0,即不允许对方再发送数据了。

在第一次调整接收窗口前,B 的应用程序从接收缓存中只读取了 100 字节,因此接收缓存还有 100 字节未被读取,可用缓存大小为 300 字节。

同理,在第二次调整窗口前,应用程序又读取了 100 字节,而在第三次调整窗口前应用程序没有读取数据,最后没有可用的接收缓存,发送方不能再发送数据。这种暂停状态将持续到主机 B 的应用程序再次从接收缓存中读取数据为止。因为当接收方的接收缓存可用空间大小不再为 0 时,会主动将更新的窗口值发送给发送方。

从该例中可以看出,接收方应用程序读取数据非常慢,但由于使用流量控制机制控制了发送方的发送速率,从而保证接收方缓存不会溢出。

发送数据大于接收速度

以上说明了 TCP 接收方是如何根据接收缓存的可用空间大小来控制 TCP 发送方的发送数据的速度,以保证接收缓存不会溢出。

但如果接收方应用程序发送数据的速度长时间大于接收方应用程序接收数据的速度,在发送方会出现什么情况呢?

从前面图5-10(a)中所示的 TCP 发送缓存与发送窗口间的关系可以看出,最终会导致 TCP 发送方的缓存被填满。这时发送应用程序必须等待,直到发送缓存有可用的空间。最终实现了发送应用程序的发送速率与接收应用程序的接收速率的匹配。

防死锁机制

但这里还存在一个问题:当接收方的可用接收缓存大小不再为 0 时,向发送方发送的窗口更新报文段丢失了会出现什么问题?

即:如果接收方一直没有数据要发送给发送方,则发送方将会永远等下去。

所以为防止因接收方发送给发送方的窗口变更报文段的丢失所导致的死锁状态,当窗口变为 0 时,如果发送方有数据要发送,则会周期性地(例如,60s)发送只包含 1 个字节数据的窗口探测(window probe)报文段,以便强制接收方发回确认并通告接收窗口大小。

如果这时接收窗口大小非零,则会接收这个字节并对该字节进行确认,否则会丢弃该字节并对以前数据进行重复确认。

拥塞控制

参考资料 网络拥塞成因与处理

待学习...

TCP 最大连接数

  • 一个网卡对应一个IP地址
  • 一个 IP 地址对应 65535 个端口
  • 一个 socket(addr, port) 可以接受多个 socket 连接(accept)
  • 一个端口只能被一个 socket 监听(listen)

待学习...

Reference

参考资料 计算机网络教程-第四版